package araxy.blog.utils;

import araxy.blog.entity.PayloadDto;
import araxy.blog.exception.TokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.nimbusds.jose.*;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.util.Base64;

@Component
public class TokenUtil {
    private static final String secret = MD5Util.getMD5("secret");
    private static String header;
    private static JWSSigner jwsSigner = SpringContextsUtil.getBean(JWSSigner.class);
    private static JWSVerifier jwsVerifier = SpringContextsUtil.getBean(JWSVerifier.class);
    private static JWSHeader jwsHeader = SpringContextsUtil.getBean(JWSHeader.class);

    @PostConstruct
    void init() {
        header = Base64.getEncoder().encodeToString(jwsHeader.toString().getBytes()) + ".";
    }

    public static String getSecret() {
        return secret;
    }

    public static PayloadDto getPayloadDto(String username,String password) {

        PayloadDto payloadDto = new PayloadDto();
        payloadDto.setExp(DateUtil.offsetDay(DateUtil.getSysTimeMS(), 30L));
        payloadDto.setUsername(username);
        payloadDto.setPassword(password);

        return payloadDto;
    }

    public static String generateTokenByHMAC(PayloadDto payloadDto) throws TokenException, JsonProcessingException {

        String payloadStr = JsonUtil.ObjectToJsonString(payloadDto);

        //将负载信息封装到Payload中
        Payload payload = new Payload(payloadStr);
        //创建JWS对象
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);
        //签名
        try {
            jwsObject.sign(jwsSigner);
        } catch (JOSEException e) {
            throw new TokenException("签名失败！");
        }
        return jwsObject.serialize().replaceAll(header,"");
    }

    public static PayloadDto verifyTokenByHMAC(String token) throws TokenException {
        token = header + token;
        //从token中解析JWS对象
        JWSObject jwsObject ;
        try {
            jwsObject = JWSObject.parse(token);
        } catch (ParseException e) {
            e.printStackTrace();
            throw new TokenException("token无法解析!");
        }
        //HMAC验证
        try {
            if (!jwsObject.verify(jwsVerifier)) {
                throw new TokenException("token签名不合法！");
            }
        } catch (JOSEException e) {
            throw new TokenException("token验证失败!");
        }

        String payload = jwsObject.getPayload().toString();
        PayloadDto payloadDto = JsonUtil.JsonStringToObject(payload, PayloadDto.class);
        if(payloadDto != null) {
            if ( payloadDto.getExp() < DateUtil.getSysTimeMS() ) {
                throw new TokenException("token已过期！");
            }
        }

        return payloadDto;
    }


}
